package dd.lo.practice;

import dd.lo.util.ImageUtils;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.commons.lang3.math.NumberUtils;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.Rect;
import org.opencv.imgcodecs.Imgcodecs;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

public class RoiAddImage extends Application {

    public static void start(String[] args) {
        launch(args);
    }

    private static final int DEFAULT_WIDTH = 1200;
    private static final int DEFAULT_HEIGHT = 900;

    private Mat srcImg;
    private Mat logoImg;
    private Mat processedImg;

    private StringProperty xs;
    private StringProperty ys;
    private StringProperty as;

    private Text errMsgText;

    private ImageView imageView;

    private void mergeImage() {
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                if (null == srcImg || srcImg.empty()) {
                    Platform.runLater(() -> errMsgText.setText("背景图片未准备好"));
                    return null;
                }
                if (null == logoImg || logoImg.empty()) {
                    Platform.runLater(() -> errMsgText.setText("LOGO图片未准备好"));
                    return null;
                }
                int x = NumberUtils.toInt(xs.get(), -1);
                if (x < 0 || x >= srcImg.width()) {
                    Platform.runLater(() -> errMsgText.setText("x输入不合法"));
                    return null;
                }
                int y = NumberUtils.toInt(ys.get(), -1);
                if (y < 0 || y >= srcImg.height()) {
                    Platform.runLater(() -> errMsgText.setText("y输入不合法"));
                    return null;
                }
                double alpha = NumberUtils.toDouble(as.get(), -1.0);
                if (alpha < 0 || alpha > 1.0) {
                    Platform.runLater(() -> errMsgText.setText("alpha输入不合法"));
                    return null;
                }
                Rect roiRect = new Rect(x, y, logoImg.width(), logoImg.height());
                processedImg = new Mat();
                srcImg.copyTo(processedImg);
                Mat roi = new Mat(processedImg, roiRect);
                Core.addWeighted(roi, alpha, logoImg, 1.0 - alpha, 0, roi);
                Mat viewImg = new Mat();
                ImageUtils.fitImgSize(processedImg, viewImg, DEFAULT_WIDTH, DEFAULT_HEIGHT);
                MatOfByte buffer = new MatOfByte();
                Imgcodecs.imencode(".jpeg", viewImg, buffer);
                Platform.runLater(() -> {
                    imageView.setImage(new Image(new ByteArrayInputStream(buffer.toArray())));
                    errMsgText.setText("");
                });
                return null;
            }
        };
        new Thread(task).start();
    }

    @Override
    public void start(Stage stage) throws Exception {
        Button bgFileChooserBtn = new Button("选择背景图片");
        bgFileChooserBtn.setOnMouseClicked(e -> {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("选择背景图片");
            fileChooser.setInitialDirectory(new File(System.getProperty("user.home") + "/Downloads")
            );
            fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("All Images", "*.*"));
            File imgFile = fileChooser.showOpenDialog(stage);
            if (null == imgFile) return;
            //读取一张图片
            srcImg = Imgcodecs.imread(imgFile.getAbsolutePath(), Imgcodecs.IMREAD_COLOR);
            if (srcImg.empty()) Platform.runLater(() -> errMsgText.setText("背景图片读取失败"));
        });
        Button logoFileChooserBtn = new Button("选择LOGO图片");
        logoFileChooserBtn.setOnMouseClicked(e -> {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("选择LOGO图片");
            fileChooser.setInitialDirectory(new File(System.getProperty("user.home") + "/Downloads")
            );
            fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("All Images", "*.*"));
            File imgFile = fileChooser.showOpenDialog(stage);
            if (null == imgFile) return; //用户取消选中文件
            //读取一张图片
            logoImg = Imgcodecs.imread(imgFile.getAbsolutePath(), Imgcodecs.IMREAD_COLOR);
            if (logoImg.empty()) Platform.runLater(() -> errMsgText.setText("LOGO图片读取失败"));
        });
        Text xTitle = new Text("LOGO粘贴位置左上角点，x=");
        TextField xInput = new TextField();
        xs = new SimpleStringProperty();
        xs.bind(xInput.textProperty());
        xInput.setText("10");
        xInput.setOnKeyReleased(event -> mergeImage());
        Text yTitle = new Text("，y=");
        TextField yInput = new TextField();
        ys = new SimpleStringProperty();
        ys.bind(yInput.textProperty());
        yInput.setText("10");
        yInput.setOnKeyReleased(event -> mergeImage());
        Text alphaTitle = new Text("，alpha=");
        TextField alphaInput = new TextField();
        as = new SimpleStringProperty();
        as.bind(alphaInput.textProperty());
        alphaInput.setText("0.5");
        alphaInput.setOnKeyReleased(event -> mergeImage());
        Button actBtn = new Button("开始");
        actBtn.setOnMouseClicked(event -> mergeImage());
        //Save button
        Button saveImgBtn = new Button("保存图片");
        saveImgBtn.setOnMouseClicked(e -> {
            if (null == processedImg || processedImg.empty()) {
                Platform.runLater(() -> errMsgText.setText("还没有处理好的图片"));
                return;
            }
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("请选择文件保存位置");
            fileChooser.setInitialDirectory(new File(System.getProperty("user.home") + "/Downloads")
            );
            File imgFile = fileChooser.showSaveDialog(stage);
            if (null == imgFile) return;
            //选中保存位置文件，进行保存
            if (!imgFile.exists()) {
                try {
                    boolean created = imgFile.createNewFile();
                    if (!created) throw new IOException("生成文件失败");
                } catch (Exception ex) {
                    Platform.runLater(() -> errMsgText.setText(ex.getMessage()));
                    return;
                }
            }
            boolean written = Imgcodecs.imwrite(imgFile.getAbsolutePath(), processedImg);
            if (!written) Platform.runLater(() -> errMsgText.setText("图片保存写入失败"));
        });
        errMsgText = new Text();
        errMsgText.setFill(Color.RED);
        Button exitBtn = new Button("关闭");
        exitBtn.setOnMouseClicked(e -> {
            Platform.exit();
        });
        FlowPane bottomControl = new FlowPane();
        bottomControl.getChildren().addAll(bgFileChooserBtn, logoFileChooserBtn, xTitle, xInput, yTitle, yInput, alphaTitle, alphaInput, actBtn, saveImgBtn, errMsgText, exitBtn);
        bottomControl.setPrefHeight(50);
        BorderPane root = new BorderPane();
        imageView = new ImageView();//imageView放到一个pane的中间
        root.setCenter(imageView);
        root.setBottom(bottomControl);
        Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT + 50);
        stage.setScene(scene);
        stage.setTitle("背景图添加LOGO工具");
        stage.setResizable(false);
        stage.show();
    }
}
